<?php

namespace org\copperforest\google;

class GOAuth
{

    const CRLF = "\r\n";

    private $CLIENT_ID;
    private $CLIENT_SECRET;

    function __construct( $client_id, $client_secret, $redirect_url )
    {
        $this->CLIENT_ID = $client_id;
        $this->CLIENT_SECRET = $client_secret;
        $this->CLIENT_REDIRECT_URI = $redirect_url;
    }

    function evaluate()
    {
        $redirect = 'http' . ((isset( $_SERVER[ 'HTTPS' ] ) && $_SERVER[ 'HTTPS' ] === 'on') ? 's' : '') . '://';
        $redirect.= ( empty( $_SERVER[ 'HTTP_HOST' ] ) ? $_SERVER[ 'SERVER_ADDR' ] : $_SERVER[ 'HTTP_HOST' ]) . ':' . $_SERVER[ 'SERVER_PORT' ];
        $redirect.= $_SERVER[ 'PHP_SELF' ];

        if ( isset( $_GET[ 'code' ] ) ) {

            //aqui obtenemos el token y obtenemos tb los datos del usuario
            $data = array(
                'code' => $_GET[ 'code' ],
                'redirect_uri' => $redirect,
                'client_id' => $this->CLIENT_ID,
                'client_secret' => $this->CLIENT_SECRET,
                'grant_type' => 'authorization_code'
            );

            $fields = array( );
            foreach ( $data as $k => $v )
                    $fields[ ] = urlencode( $k ) . '=' . urlencode( $v );

            $sp = fsockopen( 'ssl://accounts.google.com', 443 );
            $req = 'POST /o/oauth2/token HTTP/1.1' . self::CRLF;
            $req .= 'Host: accounts.google.com' . self::CRLF;
            $req .= 'Content-Type: application/x-www-form-urlencoded' . self::CRLF;
            $req .= 'Connection: Close' . self::CRLF;

            fwrite( $sp, $req );

            $req = implode( '&', $fields );

            $req = 'Content-Length: ' . strlen( $req ) . self::CRLF . self::CRLF . $req;

            fwrite( $sp, $req );


            list($code, $headers, $content) = self::getHTTPResponse( $sp );
            fclose( $sp );

            if ( $code == '200' ) {
                $values = array( );
                if ( function_exists( 'json_decode' ) )
                        $values = json_decode( $content, true );

                else {

                    //voy a simplificar esto para que sea más generalista
                    $coincidencias = array( );
                    preg_match_all( '/"([^"]*)"\s*:\s*([^,}]*)/', $content,
                            $coincidencias );

                    $values = array( );
                    $num = count( $coincidencias[ 1 ] );
                    for ( $i = 0; $i < $num; $i++ ) {
                        $coin = array( );

                        if ( preg_match( '/"([^"]*)"/',
                                        $coincidencias[ 2 ][ $i ], $coin ) )
                                $values[ $coincidencias[ 1 ][ $i ] ] = $coin[ 1 ];

                        else if ( preg_match( '/(\d*)/',
                                        $coincidencias[ 2 ][ $i ], $coin ) )
                                $values[ $coincidencias[ 1 ][ $i ] ] = ( int ) $coin[ 1 ];
                    }
                }
                unset( $headers, $content );

                $sp = fsockopen( 'ssl://www.googleapis.com', 443 );
                $req = 'GET /oauth2/v1/userinfo?access_token=' . $values[ 'access_token' ] . ' HTTP/1.1' . self::CRLF;
                $req .= 'Host: www.googleapis.com' . self::CRLF;
                $req .= 'Connection: Close' . self::CRLF . self::CRLF;

                fwrite( $sp, $req );

                list($code, $headers, $content) = self::getHTTPResponse( $sp );

                if ( function_exists( 'json_decode' ) )
                        $values = json_decode( $content, true );

                else {

                    //voy a simplificar esto para que sea más generalista
                    $coincidencias = array( );
                    preg_match_all( '/"([^"]*)"\s*:\s*([^,}]*)/', $content,
                            $coincidencias );

                    $values = array( );
                    $num = count( $coincidencias[ 1 ] );
                    for ( $i = 0; $i < $num; $i++ ) {
                        $coin = array( );

                        if ( preg_match( '/"([^"]*)"/',
                                        $coincidencias[ 2 ][ $i ], $coin ) )
                                $values[ $coincidencias[ 1 ][ $i ] ] = $coin[ 1 ];

                        else if ( preg_match( '/(\d*)/',
                                        $coincidencias[ 2 ][ $i ], $coin ) )
                                $values[ $coincidencias[ 1 ][ $i ] ] = ( int ) $coin[ 1 ];
                    }
                }

                return $values;
            }
            else {
                return false;
            }
        } else if ( isset( $_GET[ 'error' ] ) ) {
            return false;
        } else {
            $data = array(
                'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
                'redirect_uri' => $redirect,
                'response_type' => 'code',
                'client_id' => $this->CLIENT_ID
            );

            $data_encoded = array( );
            foreach ( $data as $k => $v )
                    $data_encoded[ ] = urlencode( $k ) . '=' . urlencode( $v );

            header( 'Location: https://accounts.google.com/o/oauth2/auth?' . implode( '&',
                            $data_encoded ) );
            exit();
        }
    }

    private static function getHTTPResponse( $socket, $fp = null )
    {
        $linea = self::CRLF;
        while ( $linea == self::CRLF )
            $linea = fgets( $socket );

        $responseCode = ( int ) substr( $linea, 9, 3 );
        //  $this->responseVersion= substr($linea,6,3);

        $responseHeaders = array( );

        $linea = substr( fgets( $socket ), 0, -2 );



        while ( !feof( $socket ) && $linea != '' ) {

            $dos_puntos = strpos( $linea, ':' );
            $name = ucwords( trim( substr( $linea, 0, $dos_puntos ) ) );
            $value = trim( substr( $linea, $dos_puntos + 1 ) );


            if ( !isset( $responseHeaders[ $name ] ) )
                    $responseHeaders[ $name ] = array( );

            $responseHeaders[ $name ][ ] = $value;


            $linea = substr( fgets( $socket ), 0, -2 );
        }


        $responseContent = '';
        if ( isset( $responseHeaders[ 'Transfer-Encoding' ] ) && $responseHeaders[ 'Transfer-Encoding' ][ 0 ] == 'chunked' ) {

            $tam = hexdec( substr( fgets( $socket ), 0, -2 ) );


            while ( !feof( $socket ) && $tam > 0 ) {

                while ( !feof( $socket ) && $tam > 0 ) {
                    $linea = fread( $socket, $tam );

                    if ( !empty( $fp ) ) fwrite( $fp, $linea );
                    else $responseContent.=$linea;

                    $tam-=strlen( $linea );
                }

                $linea = fgets( $socket );

                while ( $linea == self::CRLF )
                    $linea = fgets( $socket );

                $tam = hexdec( substr( $linea, 0, -2 ) );
            }
        }
        else if ( isset( $responseHeaders[ 'Content-Length' ] ) ) {

            $tam = ( int ) $responseHeaders[ 'Content-Length' ][ 0 ];

            while ( !feof( $socket ) && $tam > 0 ) {
                $linea = fread( $socket, $tam );

                if ( !empty( $fp ) ) fwrite( $fp, $linea );
                else $responseContent.=$linea;

                $tam-=strlen( $linea );
            }
        }
        else {
            while ( !feof( $socket ) ) {
                $linea = fread( $socket, 1024 );

                if ( !empty( $fp ) ) fwrite( $fp, $linea );
                else $responseContent.=$linea;
            }
        }

        return array( $responseCode, $responseHeaders, $responseContent );
    }

}

?>
